﻿using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.DataSourcesRaster;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geoprocessor;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geoprocessing;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.SpatialAnalystTools;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.SystemUI;

namespace School
{
    public partial class Slope : Form
    {
        private AxMapControl _mapControl;

        public Slope(AxMapControl mapControl)
        {
            InitializeComponent();
            _mapControl = mapControl;
            Load += Slope_Load;
        }

        private void Slope_Load(object sender, EventArgs e)
        {
            cboInput.Items.Clear();
            if (this._mapControl.LayerCount <= 0)
                return;

            ILayer pLayer;
            string strLayerName;
            for (int i = 0; i < this._mapControl.LayerCount; i++)
            {
                pLayer = this._mapControl.get_Layer(i);
                strLayerName = pLayer.Name;
                this.cboInput.Items.Add(strLayerName);
            }
            this.cboInput.SelectedIndex = 0;

            string tempDir = @"D:\Temp\";
            txtOutput.Text = System.IO.Path.Combine(tempDir, ((string)cboInput.SelectedItem + "_buffer.shp"));

            this.cboUnit.Items.Add("度");
            this.cboUnit.Items.Add("百分比");

            this.cboUnit.SelectedIndex = 0;

            cboMethod.Items.Add("平面");
            cboMethod.Items.Add("测地线");
            cboMethod.SelectedIndex = 0;

            cboZUnit.Items.Add("METER");
            cboZUnit.Items.Add("FOOT");
            cboZUnit.Items.Add("KILOMETER");
            cboZUnit.Items.Add("MILE_US");
            cboZUnit.Items.Add("NAUTICAL_MILE");
            cboZUnit.Items.Add("YARD");
            cboZUnit.Items.Add("INCH");
            cboZUnit.Items.Add("CENTIMETER");
            cboZUnit.Items.Add("MILLIMETER");
            cboZUnit.Items.Add("DECIMETER");

            // 设置Z因子默认值
            txtZFactor.Text = "1";

            cboInput.SelectedIndexChanged += CboInput_SelectedIndexChanged;

            UpdateZUnitFromSelectedRaster();
        }

        private void CboInput_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateZUnitFromSelectedRaster();
        }

        private void UpdateZUnitFromSelectedRaster()
        {
            try
            {
                string layerName = cboInput.SelectedItem.ToString();
                IRasterLayer rasterLayer = GetRasterLayerByName(layerName);

                if (rasterLayer != null)
                {
                    string zUnit = AutoDetectZUnitFromRaster(rasterLayer);
                    if (!string.IsNullOrEmpty(zUnit))
                    {
                        // 设置Z单位下拉框选择项
                        for (int i = 0; i < cboZUnit.Items.Count; i++)
                        {
                            if (cboZUnit.Items[i].ToString() == zUnit)
                            {
                                cboZUnit.SelectedIndex = i;
                                break;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"自动检测Z单位时出错: {ex.Message}", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }


        private string AutoDetectZUnitFromRaster(IRasterLayer rasterLayer)
        {
            try
            {
                IRaster2 raster = (IRaster2)rasterLayer.Raster;
                IRasterDataset rasterDataset = raster.RasterDataset;

                ISpatialReference spatialRef = null;
                if (rasterDataset is IGeoDataset geoDataset)
                {
                    spatialRef = geoDataset.SpatialReference;
                }

                if (spatialRef != null)
                {
                    int wkid = spatialRef.FactoryCode;
                    if (wkid != 0 && wkid != 4326) // 4326为未指定投影的地理坐标系
                    {
                        ILinearUnit linearUnit = spatialRef.ZCoordinateUnit as ILinearUnit;
                        if (linearUnit != null)
                        {
                            // 替代Type属性：通过单位名称映射单位类型
                            string unitName = linearUnit.Name.ToUpperInvariant();

                            if (unitName.Contains("METER"))
                                return "METER";
                            else if (unitName.Contains("FOOT") || unitName.Contains("FEET"))
                                return "FOOT";
                            else if (unitName.Contains("KILOMETER"))
                                return "KILOMETER";
                            else if (unitName.Contains("MILE"))
                                return "MILE_US";
                            else if (unitName.Contains("NAUTICAL"))
                                return "NAUTICAL_MILE";
                            else if (unitName.Contains("YARD"))
                                return "YARD";
                            else if (unitName.Contains("INCH"))
                                return "INCH";
                            else if (unitName.Contains("CENTIMETER"))
                                return "CENTIMETER";
                            else if (unitName.Contains("MILLIMETER"))
                                return "MILLIMETER";
                            else if (unitName.Contains("DECIMETER"))
                                return "DECIMETER";
                            else
                                return "METER"; // 默认使用米
                        }
                    }
                }

                return "METER"; // 如果无法检测，默认使用米
            }
            catch (Exception ex)
            {
                MessageBox.Show($"获取栅格空间参考时出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return "METER"; // 出错时默认使用米
            }
        }

        private void btnOutput_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveDlg = new SaveFileDialog();
            saveDlg.CheckPathExists = true;
            saveDlg.Filter = "Shapefile (*.shp)|*.shp";
            saveDlg.OverwritePrompt = true;
            saveDlg.Title = "输出路径";
            saveDlg.RestoreDirectory = true;
            saveDlg.FileName = (string)cboInput.SelectedItem + "_buffer.shp";

            //读取文件输出路径到txtOutputPath
            DialogResult dr = saveDlg.ShowDialog();
            if (dr == DialogResult.OK)
                txtOutput.Text = saveDlg.FileName;
        }

        private void ExecuteSlopeAnalysis(IRasterLayer inputRasterLayer)
        {
            try
            {
                Geoprocessor gp = new Geoprocessor();
                gp.OverwriteOutput = true;

                ESRI.ArcGIS.SpatialAnalystTools.Slope slopeTool = new ESRI.ArcGIS.SpatialAnalystTools.Slope();
                slopeTool.in_raster = inputRasterLayer.Raster;

                string outputPath = System.IO.Path.Combine(
                    System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location),
                    "SlopeOutput.tif");
                slopeTool.out_raster = outputPath;

                if (cboUnit.SelectedItem != null)
                {
                    string selectedUnit = cboUnit.SelectedItem.ToString();
                    slopeTool.output_measurement = selectedUnit == "度" ? "DEGREE" : "PERCENT_RISE";
                }

                if (cboMethod.SelectedItem != null)
                {
                    string selectedMethod = cboMethod.SelectedItem.ToString();
                    slopeTool.method = selectedMethod == "平面" ? "PLANAR" : "GEODESIC";
                }

                if (cboZUnit.SelectedItem != null)
                {
                    slopeTool.z_unit = cboZUnit.SelectedItem.ToString();
                }

                if (!string.IsNullOrEmpty(txtZFactor.Text) && double.TryParse(txtZFactor.Text, out double zFactor))
                {
                    slopeTool.z_factor = zFactor;
                }

                IGeoProcessorResult result = (IGeoProcessorResult)gp.Execute(slopeTool, null);

                if (result.Status == esriJobStatus.esriJobSucceeded)
                {
                    string outputRasterPath = result.GetOutput(0).GetAsText();

                    IRasterLayer outputLayer = new RasterLayerClass();
                    outputLayer.CreateFromFilePath(outputRasterPath);
                    outputLayer.Name = "坡度分析结果";

                    _mapControl.AddLayer((ILayer)outputLayer);
                    _mapControl.Refresh();
                }
                else
                {
                    string message = string.Join("\r\n", Enumerable.Range(0, gp.MessageCount).Select(i => gp.GetMessage(i)));
                    MessageBox.Show($"分析完成但状态异常: {message}", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"执行坡度分析时出错：{ex.Message}");
            }
        }

        private IRasterLayer GetRasterLayerByName(string layerName)
        {
            for (int i = 0; i < _mapControl.LayerCount; i++)
            {
                ILayer layer = _mapControl.get_Layer(i);
                if (layer is IRasterLayer && layer.Name == layerName)
                {
                    return layer as IRasterLayer;
                }
            }
            return null;
        }

        // 坡度分析按钮点击事件
        private void btnAnalyze_Click(object sender, EventArgs e)
        {
            IRasterLayer inputRasterLayer = GetRasterLayerByName(cboInput.SelectedItem.ToString());
            try
            {
                ExecuteSlopeAnalysis(inputRasterLayer);
                MessageBox.Show("坡度分析完成！", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"坡度分析失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnBack_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btnInput_Click(object sender, EventArgs e)
        {
            ICommand cmd = new ControlsAddDataCommandClass();
            cmd.OnCreate(_mapControl.Object);
            cmd.OnClick();
        }
    }

}
